Skip to content

feat: add {progress} format token to hierarchy issue rows#279

Merged
miroslavpojer merged 6 commits intomasterfrom
feature/277-Add-{progress}-format-token-to-hierarchy-issue-rows
Apr 1, 2026
Merged

feat: add {progress} format token to hierarchy issue rows#279
miroslavpojer merged 6 commits intomasterfrom
feature/277-Add-{progress}-format-token-to-hierarchy-issue-rows

Conversation

@miroslavpojer
Copy link
Copy Markdown
Collaborator

@miroslavpojer miroslavpojer commented Mar 30, 2026

Overview

Adds a {progress} format token to row-format-hierarchy-issue. When enabled, each hierarchy issue row shows how many of its direct sub-issues are closed vs total (e.g. 2/3 done). Leaf nodes (no direct sub-issues) return an empty string so the token collapses cleanly without leaving extra whitespace. Progress counts direct children only — no recursive aggregation — so each level in a nested hierarchy reports independently.

The token is opt-in: the default row format is unchanged, making this fully backward-compatible.

Release Notes

  • Add {progress} format token to row-format-hierarchy-issue showing direct sub-issue completion as X/Y done
  • Leaf hierarchy nodes (no direct sub-issues) suppress {progress} cleanly via whitespace normalisation

Related

Closes #277

Summary by CodeRabbit

  • New Features

    • Progress counts added to hierarchy issues, showing direct-child completion per level (e.g., "2/3 done"); leaf nodes suppress the token to avoid extra whitespace.
    • Hierarchy row formatting now supports a progress token for displays.
  • Documentation

    • Added docs and examples describing the {progress} token, its rendering rules, and omission behavior.
  • Tests

    • Unit tests added for progress rendering, mixed child types, per-level independence, and change-detection logic.

Add a `progress` property to `HierarchyIssueRecord` that returns 'X/Y done'
counting direct closed children vs total direct children (sub-issues and
sub-hierarchy-issues, no recursion). Leaf nodes return '' so the token
collapses cleanly in bare whitespace context via `format_row_with_suppression`.

Register `progress` in `SUPPORTED_ROW_FORMAT_KEYS_HIERARCHY_ISSUE` so the
format-string validator accepts it without stripping.

- release_notes_generator/utils/constants.py: add "progress" to supported keys
- release_notes_generator/model/record/hierarchy_issue_record.py: add progress
  property; pass format_values["progress"] in to_chapter_row()
- tests/unit/release_notes_generator/model/test_hierarchy_issue_record.py: new
  file — 9 tests covering leaf, partial, full, all-open, mixed children,
  row rendering, whitespace suppression, delimiter adjacency, per-level
  independence
- docs/features/issue_hierarchy_support.md: document {progress} token and
  update Example Result section
@miroslavpojer miroslavpojer self-assigned this Mar 30, 2026
@miroslavpojer miroslavpojer requested a review from Copilot March 30, 2026 13:54
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 30, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: bcfa3930-27f6-4b64-8d1f-37d53a5acaf0

📥 Commits

Reviewing files that changed from the base of the PR and between e4391c0 and 5b29cc7.

📒 Files selected for processing (24)
  • release_notes_generator/model/record/hierarchy_issue_record.py
  • tests/integration/integration_test.py
  • tests/integration/test_release_notes_snapshot.py
  • tests/unit/conftest.py
  • tests/unit/release_notes_generator/builder/test_release_notes_builder.py
  • tests/unit/release_notes_generator/chapters/test_chapter.py
  • tests/unit/release_notes_generator/chapters/test_custom_chapters.py
  • tests/unit/release_notes_generator/chapters/test_service_chapters.py
  • tests/unit/release_notes_generator/data/test_filter.py
  • tests/unit/release_notes_generator/data/test_miner.py
  • tests/unit/release_notes_generator/data/utils/test_bulk_sub_issue_collector.py
  • tests/unit/release_notes_generator/model/conftest.py
  • tests/unit/release_notes_generator/model/test_commit_record.py
  • tests/unit/release_notes_generator/model/test_hierarchy_issue_record.py
  • tests/unit/release_notes_generator/model/test_issue_record.py
  • tests/unit/release_notes_generator/model/test_issue_record_row_formatting.py
  • tests/unit/release_notes_generator/model/test_pull_request_record.py
  • tests/unit/release_notes_generator/model/test_record.py
  • tests/unit/release_notes_generator/record/factory/test_default_record_factory.py
  • tests/unit/release_notes_generator/test_action_inputs.py
  • tests/unit/release_notes_generator/test_generator.py
  • tests/unit/release_notes_generator/utils/test_gh_action.py
  • tests/unit/release_notes_generator/utils/test_pull_request_utils.py
  • tests/unit/release_notes_generator/utils/test_utils.py
💤 Files with no reviewable changes (4)
  • tests/unit/release_notes_generator/chapters/test_service_chapters.py
  • tests/unit/release_notes_generator/chapters/test_chapter.py
  • tests/unit/release_notes_generator/utils/test_utils.py
  • tests/unit/release_notes_generator/utils/test_gh_action.py
✅ Files skipped from review due to trivial changes (16)
  • tests/unit/release_notes_generator/data/utils/test_bulk_sub_issue_collector.py
  • tests/unit/release_notes_generator/model/test_commit_record.py
  • tests/unit/release_notes_generator/model/test_issue_record.py
  • tests/unit/release_notes_generator/model/test_pull_request_record.py
  • tests/unit/release_notes_generator/model/test_issue_record_row_formatting.py
  • tests/unit/release_notes_generator/utils/test_pull_request_utils.py
  • tests/unit/release_notes_generator/model/test_record.py
  • tests/integration/integration_test.py
  • tests/unit/release_notes_generator/test_generator.py
  • tests/integration/test_release_notes_snapshot.py
  • tests/unit/release_notes_generator/test_action_inputs.py
  • tests/unit/release_notes_generator/chapters/test_custom_chapters.py
  • tests/unit/release_notes_generator/record/factory/test_default_record_factory.py
  • tests/unit/release_notes_generator/model/conftest.py
  • tests/unit/release_notes_generator/data/test_filter.py
  • tests/unit/conftest.py

Walkthrough

Adds a {progress} format token for hierarchy-issue rows: implements HierarchyIssueRecord.progress (counts direct children only, returns "" for leaf nodes), wires it into to_chapter_row() as format_values["progress"], updates supported keys, adds docs, fixtures, and unit tests including contains_change_increment() logic.

Changes

Cohort / File(s) Summary
Documentation
docs/features/issue_hierarchy_support.md
Document {progress} token, "X/Y done" output, direct-child counting, leaf suppression, config snippet and example output.
Hierarchy record implementation
release_notes_generator/model/record/hierarchy_issue_record.py
Added HierarchyIssueRecord.progress property (direct-child counts; "" for no children), added contains_change_increment() for change-detection, and set format_values["progress"] in to_chapter_row().
Constants
release_notes_generator/utils/constants.py
Added "progress" to SUPPORTED_ROW_FORMAT_KEYS_HIERARCHY_ISSUE.
Tests & fixtures
tests/unit/release_notes_generator/model/test_hierarchy_issue_record.py, tests/unit/release_notes_generator/model/conftest.py
New unit tests for progress formatting, suppression behavior, per-level counting, mixed child types, and contains_change_increment(); added factory fixtures to create mocked hierarchy/sub-issue records.
Guidance & linting
.github/copilot-instructions.md
Extended pytest guidance: avoid referencing private members in tests, centralize helpers in nearest conftest.py, and type-annotate fixture factory signatures.
Other tests (formatting/whitespace)
tests/... (many files)
Multiple test files reformatted for readability (whitespace, multi-line signatures/patch calls, quoting style); no behavior changes.

Sequence Diagram(s)

(omitted)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

Possibly related PRs

Suggested labels

enhancement

Suggested reviewers

  • Zejnilovic
  • lsulak

Poem

🐰 I hop through rows and tally cheer,
Little ticks of progress, bright and clear.
Two of three done — a gentle chime,
Leaves stay quiet, saving space and time.
Rabbit counts, the notes now rhyme.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 19.17% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding a {progress} format token to hierarchy issue rows, which is the core feature across all modifications.
Description check ✅ Passed The PR description includes Overview, Release Notes, and Related sections matching the template structure with substantive content for all required sections.
Linked Issues check ✅ Passed All coding requirements from issue #277 are met: progress property added to HierarchyIssueRecord, leaf nodes return empty string, progress counts direct children only, constant/documentation updated, and comprehensive tests included.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing the {progress} token feature. Test refactoring, formatting improvements, and documentation updates are all in scope for feature development and code quality.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/277-Add-{progress}-format-token-to-hierarchy-issue-rows

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an opt-in {progress} format token for hierarchy issue rows so release notes can show direct child completion (closed/total) per hierarchy level.

Changes:

  • Add HierarchyIssueRecord.progress and expose it as {progress} in row-format-hierarchy-issue.
  • Extend hierarchy row-format keyword validation to allow progress.
  • Add unit tests covering leaf suppression, formatting behavior, and per-level counting; update hierarchy docs.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
release_notes_generator/model/record/hierarchy_issue_record.py Computes direct-child progress and injects it into hierarchy row formatting values.
release_notes_generator/utils/constants.py Adds progress to supported hierarchy row-format keys for validation/cleaning.
tests/unit/release_notes_generator/model/test_hierarchy_issue_record.py New unit tests for progress computation and rendering/suppression behavior.
docs/features/issue_hierarchy_support.md Documents {progress} token and updates examples (currently inconsistent with actual rendering behavior).

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
tests/unit/release_notes_generator/model/test_hierarchy_issue_record.py (1)

30-63: Consider de-duplicating the mock issue builders.

_make_hierarchy_issue and _make_sub_issue repeat almost the same mock setup; a shared helper would reduce maintenance overhead.

Optional refactor sketch
+def _make_issue_mock(mocker, number: int, state: str, title_prefix: str) -> Issue:
+    issue = mocker.Mock(spec=Issue)
+    issue.number = number
+    issue.title = f"{title_prefix}{number}"
+    issue.state = state
+    issue.state_reason = None
+    issue.body = ""
+    issue.type = None
+    issue.created_at = datetime.now()
+    issue.closed_at = datetime.now() if state == IssueRecord.ISSUE_STATE_CLOSED else None
+    issue.repository.full_name = "org/repo"
+    issue.user = None
+    issue.assignees = []
+    issue.get_labels.return_value = []
+    issue.get_sub_issues.return_value = []
+    return issue
+
 def _make_hierarchy_issue(mocker, number: int, state: str) -> Issue:
-    issue = mocker.Mock(spec=Issue)
-    issue.number = number
-    issue.title = f"HI{number}"
-    issue.state = state
-    issue.state_reason = None
-    issue.body = ""
-    issue.type = None
-    issue.created_at = datetime.now()
-    issue.closed_at = datetime.now() if state == IssueRecord.ISSUE_STATE_CLOSED else None
-    issue.repository.full_name = "org/repo"
-    issue.user = None
-    issue.assignees = []
-    issue.get_labels.return_value = []
-    issue.get_sub_issues.return_value = []
-    return issue
+    return _make_issue_mock(mocker, number, state, "HI")
 
 def _make_sub_issue(mocker, number: int, state: str) -> SubIssueRecord:
-    issue = mocker.Mock(spec=Issue)
-    issue.number = number
-    issue.title = f"SI{number}"
-    issue.state = state
-    issue.state_reason = None
-    issue.body = ""
-    issue.type = None
-    issue.created_at = datetime.now()
-    issue.closed_at = datetime.now() if state == IssueRecord.ISSUE_STATE_CLOSED else None
-    issue.repository.full_name = "org/repo"
-    issue.user = None
-    issue.assignees = []
-    issue.get_labels.return_value = []
-    issue.get_sub_issues.return_value = []
-    return SubIssueRecord(issue)
+    return SubIssueRecord(_make_issue_mock(mocker, number, state, "SI"))
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/unit/release_notes_generator/model/test_hierarchy_issue_record.py`
around lines 30 - 63, Both _make_hierarchy_issue and _make_sub_issue duplicate
the same mock Issue construction; extract a shared helper (e.g.,
_build_mock_issue) that accepts parameters like mocker, number, state and
returns the configured mock Issue, then have _make_hierarchy_issue call this
helper and return the Issue, and have _make_sub_issue call the helper and wrap
the returned mock with SubIssueRecord(issue); update references to
IssueRecord.ISSUE_STATE_CLOSED, get_labels, get_sub_issues,
repository.full_name, and other fields inside the new helper to preserve current
behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@tests/unit/release_notes_generator/model/test_hierarchy_issue_record.py`:
- Around line 30-63: Both _make_hierarchy_issue and _make_sub_issue duplicate
the same mock Issue construction; extract a shared helper (e.g.,
_build_mock_issue) that accepts parameters like mocker, number, state and
returns the configured mock Issue, then have _make_hierarchy_issue call this
helper and return the Issue, and have _make_sub_issue call the helper and wrap
the returned mock with SubIssueRecord(issue); update references to
IssueRecord.ISSUE_STATE_CLOSED, get_labels, get_sub_issues,
repository.full_name, and other fields inside the new helper to preserve current
behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 10deba2a-7631-442d-9126-915ea7ca67e3

📥 Commits

Reviewing files that changed from the base of the PR and between 28f5bcc and 2601a6f.

📒 Files selected for processing (4)
  • docs/features/issue_hierarchy_support.md
  • release_notes_generator/model/record/hierarchy_issue_record.py
  • release_notes_generator/utils/constants.py
  • tests/unit/release_notes_generator/model/test_hierarchy_issue_record.py

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/unit/release_notes_generator/model/conftest.py`:
- Around line 29-30: The fixtures make_hierarchy_issue and make_sub_issue need
explicit type annotations: add MockerFixture to the mocker parameter and
annotate the fixture return type as a Callable (e.g., Callable[..., dict] or
Callable[..., YourIssueType]) to satisfy mypy; import MockerFixture from
pytest_mock and Callable from typing, then update the signatures for
make_hierarchy_issue(mocker: MockerFixture) -> Callable[...] and
make_sub_issue(mocker: MockerFixture) -> Callable[...] accordingly and adjust
any inline return/type hints to match the actual returned callable shape.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c208aecb-f692-4b20-b06d-51fdee408070

📥 Commits

Reviewing files that changed from the base of the PR and between caba6aa and 44d697a.

📒 Files selected for processing (4)
  • .github/copilot-instructions.md
  • release_notes_generator/model/record/hierarchy_issue_record.py
  • tests/unit/release_notes_generator/model/conftest.py
  • tests/unit/release_notes_generator/model/test_hierarchy_issue_record.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/unit/release_notes_generator/model/test_hierarchy_issue_record.py
  • release_notes_generator/model/record/hierarchy_issue_record.py

Copy link
Copy Markdown
Collaborator

@tmikula-dev tmikula-dev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Logic looks correct to me, I like the feature. Please react to the comments, that I left in the review.

Copy link
Copy Markdown
Collaborator

@tmikula-dev tmikula-dev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, thanks. Approving.

@miroslavpojer miroslavpojer merged commit 77b645a into master Apr 1, 2026
9 checks passed
@miroslavpojer miroslavpojer deleted the feature/277-Add-{progress}-format-token-to-hierarchy-issue-rows branch April 1, 2026 09:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add {progress} format token to hierarchy issue rows

3 participants